遗传算法以及求解TSP介绍http://blog.csdn.net/bizer_csdn/article/details/51760110
要求是从a点出发,对结束点没要求,但必须经过所有点,并且允许重复。
这个问题不同于TSP,但是稍加改进就可以了。
其实,主要就是邻接矩阵中,任意两点之间存储的是两点之间的最短距离,比如,a---f之间的最短距离是2+1+3=6。
关于两点之间最短路径问题,这题给出的权重是正值,感觉可以使用dijkstra之类的算法,当初是手算的,以后有机会慢慢补充。
下面给出代码:
GA.cpp
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
const double P_MAT=0.8; //交配概率
const double P_VAR=0.001; //变异概率
const int TMAX=150; //最大迭代次数
const int N=11; //11个城市
const int INF=1000; //表示图中不连通部分权重
const int GROUP_SIZE=300;//种群大小,300
vector<int> GROUP[GROUP_SIZE]; //种群
//邻接矩阵中存的是任意两节点的最短路径
int pointdist[N][N]={
{ 0, 2, 7, 1, 3, 6, 10, 5, 12, 11, 14},
{ 2, 0, 5, 3, 1, 4, 8, 3, 10, 11, 12},
{ 7, 5, 0, 7, 4, 1, 5, 6, 7, 6, 9},
{ 1, 3, 7, 0, 4, 7, 9, 6, 11, 10, 13},
{ 3, 1, 4, 4, 0, 3, 7, 2, 9, 10, 11},
{ 6, 4, 1, 7, 3, 0, 4, 5, 6, 5, 8},
{ 10, 8, 5, 9, 7, 4, 0, 9, 2, 1, 4},
{ 5, 3, 6, 6, 2, 5, 9, 0, 7, 8, 9},
{ 12, 10, 7, 11, 9, 6, 2, 7, 0, 1, 2},
{ 11, 11, 6, 10, 10, 5, 1, 8, 1, 0, 3},
{ 14, 12, 9, 13, 11, 8, 4, 9, 2, 3, 0}};
//随机产生一个新的基因
void newChrom(vector<int>& chrom)
{
chrom.clear();
//保证第一城市为'a'
for(int i=0;i<N;i++)
{
chrom.push_back(i);
}
int i=0,j=0;
do
{
i=rand()%(N-1)+1;
j=rand()%(N-1)+1;
} while (!(i<j));//生成两个不同随机数
//逆序法生成新染色体
while(i<j)
{
swap(chrom[i++],chrom[j--]);
}
}
//种群初始化
void group_init()
{
for(int i=0;i<GROUP_SIZE;i++){
newChrom(GROUP[i]);
}
}
//计算每个染色体的适应值函数,即距离
int chrom_len(vector<int> chrom)
{
int len=0;
for(int i=0;i<chrom.size()-1;i++){
int p1=chrom[i];
int p2=chrom[i+1];
len=len+pointdist[p1][p2];
}
return len;
}
bool descend_by_len(vector<int> chrom1,vector<int> chrom2)
{
return chrom_len(chrom1)>chrom_len(chrom2);
}
//选择
void choose()
{
//适应值函数为距离之和
//为了加速进化过程,按着适应值函数从大到小进行排序
//排序后,第i染色体被选中概率为2*i/GROUP_SIZE/(GROUP_SIZE+1)
//采样“轮盘赌”算法模拟第i染色体被选中
//"轮盘赌"算法进行选择
//按着适应值函数从大到小进行排序,并计算排序后每个染色体被选中的概率
vector<int> new_group[GROUP_SIZE];
sort(GROUP,GROUP+GROUP_SIZE,descend_by_len);
double p[GROUP_SIZE]={0.0};
for(int i=0;i<GROUP_SIZE;i++){
p[i]=(double)2*(i+1)/GROUP_SIZE/(GROUP_SIZE+1);
}
//进行GROUP_SIZE次选择
for(int i=0;i<GROUP